/**
 * 
 */
package erlangtools.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;



public class AnalysisState implements Iterable<ReplaceDescription> {
	private List<ReplaceLevel> levels = new ArrayList<ReplaceLevel>();

	private Map<Integer, Map<Integer, ReplaceDescription>> repsMap = new HashMap<Integer, Map<Integer, ReplaceDescription>>();
	private Map<Integer, Integer> typesMax = new HashMap<Integer, Integer>();
	
	public ReplaceLevel newLevel() {
		ReplaceLevel level = new ReplaceLevel(levels.size());
		levels.add(level);
		return level;
	}
	
	public ReplaceLevel getLevel(int i) {
		return levels.get(i);
	}
	
	public int currentLevel() {
		return levels.size() - 1;
	}
	
	public void addRep(int level, ReplaceDescription rep) {
		levels.get(level).addRep(rep);
		int type = rep.getType();
		if (repsMap.get(type) == null) repsMap.put(type, new HashMap<Integer, ReplaceDescription>());
		repsMap.get(type).put(rep.getId(), rep);
		if (getTypeMax(type) < rep.getId()) typesMax.put(type, rep.getId());
	}

	public ReplaceDescription getRep(int type, int id) {
		if (repsMap.get(type) == null) return null;
		else return repsMap.get(type).get(id);
	}
	
	public int getTypeMax(int type) {
		if (typesMax.get(type) == null) return 0;
		else return typesMax.get(type);
	}

	public Iterator<ReplaceDescription> iterator() {
		return new Iterator<ReplaceDescription>() {
			private int level;
			private Iterator<ReplaceDescription> current = null;

			{
				level = 0;
				if (levels.size() > 0) {
					current = levels.get(level).iterator();
					while (level < levels.size() && !current.hasNext()) {
						level++;
						current = levels.get(level).iterator();
					}
				}
			}
			
			public boolean hasNext() {
				if (current.hasNext()) return true;
				level++;
				while (level < levels.size() && !current.hasNext()) {
					current = levels.get(level).iterator();
					level++;
				}
				return level < levels.size();
			}

			public ReplaceDescription next() {
				while (!current.hasNext()) {
					level++;
					current = levels.get(level).iterator();
				}
				return current.next();
			}

			public void remove() {
				throw new RuntimeException("Remove not allowed");
			}
			
		};
	}
}